import {defineComponent, h, PropType} from "vue";
import {Dialog} from "vant";
import {showComponentToBody} from "@/utils";
import Toast from './Toast'

const Notify = defineComponent({
  name: 'Notify',
  emits: ['confirm', 'cancel', 'close'],
  props: {
    messageType: {
      type: String as PropType<'confirm' | 'success' | 'info' | 'error'>,
      default: 'cofirm'
    },
    title: {
      type: [String, Function],
      default: undefined
    },
    message: {
      type: String,
      default: undefined
    },
    callbak: {
      type: Object,
      default: () => ({
        confirm: (close: Function): boolean => true,
        cancel: (close: Function): boolean => true
      })
    }
  },
  data() {
    return {
      show: true
    }
  },
  render() {
    if (this.messageType === 'confirm') {
      return this.renderConfirm()
    } else {
      return this.renderMsgBox()
    }
  },
  methods: {
    createBeforePromise(action: any) {
      if(!action) action = 'cancel';
      return new Promise(() => {
        const close = () => this.show = false
        if (action === 'confirm' && this.callbak && this.callbak.confirm) {
          this.callbak.confirm(close);
        }
        if (action === 'cancel' && this.callbak && this.callbak.cancel) {
          this.callbak.cancel(close)
        }
      });
    },
    renderMsgBox() {
      return h(Dialog, {
        show: this.show,
        //@ts-ignore
        title: this.title,
        message: this.message,
        closeOnClickOverlay: true,
        'show-cancel-button': false,
        //@ts-ignore
        beforeClose: (action: any) => this.createBeforePromise(action)
      });
    },
    renderConfirm() {
      return h(Dialog, {
        show: this.show,
        //@ts-ignore
        title: this.title,
        message: this.message,
        closeOnClickOverlay: true,
        'show-cancel-button': true,
        //@ts-ignore
        beforeClose: (action: any) => this.createBeforePromise(action)
      });
    }
  },
  watch: {
    show() {
      if (!this.show) {
        this.$emit('close')
      }
    },
  }
});

type NotifyConfig = {
  title: string;
  message?: string;
  type: 'confirm' | 'success' | 'info' | 'error' | 'toast';
  confirm?: Function,
  cancel?: Function,
}

const $notify = function (config: NotifyConfig) {
  if (['confirm', 'success', 'info', 'error'].includes(config.type)) {
    return renderConfirm(config);
  } else {
    return Toast(config)
  }
};

function renderConfirm(config: NotifyConfig) {
  let win = h(Notify, {
    //@ts-ignore
    messageType: config.type,
    title: config.title,
    message: config.message,
    callbak: {
      confirm(close: Function) {
        if (config.confirm) {
          let res: any = undefined;
          try {
            res = config.confirm(close);
          } catch (e) {
            console.error(e);
            res = undefined
          }
          if (!res) {
            close(true)
          }
        } else {
          close(true)
        }
      },
      cancel(close: Function) {
        if (config.cancel) {
          let res: any = undefined;
          try {
            res = config.cancel(close);
          } catch (e) {
            console.error(e);
            res = undefined
          }
          if (!res) {
            close(true)
          }
        } else {
          close(true)
        }
      }
    }
  });
  showComponentToBody(win);
  return win;
}

export {$notify};
export default Notify;